package com.ss.ugc.android.alphavideoplayer.player

import android.content.Context
import android.net.Uri
import android.util.Log
import android.view.Surface
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Format
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.SingleSampleMediaSource
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter
import com.google.android.exoplayer2.upstream.DefaultDataSource
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.upstream.FileDataSource
import com.google.android.exoplayer2.util.MimeTypes
import com.google.android.exoplayer2.video.VideoSize
import com.ss.ugc.android.alpha_player.model.VideoInfo
import com.ss.ugc.android.alpha_player.player.AbsPlayer


/**
 * created by dengzhuoyao on 2020/07/08
 *
 * Implemented by ExoPlayer.
 */
class ExoPlayerImpl(private val context: Context) : AbsPlayer(context) {

    private val TAG = "ExoPlayerImpl"
    private lateinit var exoPlayer: ExoPlayer

    private var videoSource: MediaSource? = null

    private var currVideoWidth: Int = 0
    private var currVideoHeight: Int = 0
    private var isLooping: Boolean = false

    private val httpDataSource =  DefaultHttpDataSource.Factory()
        .setAllowCrossProtocolRedirects(true)
        .setConnectTimeoutMs(50000)
        .setReadTimeoutMs(50000)
        .setTransferListener(DefaultBandwidthMeter.Builder(context).build())

    private val fileDataSource = FileDataSource.Factory()

    private val exoPlayerListener: Player.Listener = object: Player.Listener {

        override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
            when (playbackState) {
                Player.STATE_READY -> {
                    if (playWhenReady) {
                        preparedListener?.onPrepared()
                    }
                }
                Player.STATE_ENDED -> {
                    completionListener?.onCompletion()
                }
                else -> {}
            }
        }

        override fun onVideoSizeChanged(videoSize: VideoSize) {
            currVideoWidth = videoSize.width
            currVideoHeight = videoSize.height
        }

        override fun onRenderedFirstFrame() {
            firstFrameListener?.onFirstFrame()
        }
    }



    override fun initMediaPlayer() {
        exoPlayer = ExoPlayer.Builder(context).build()
        exoPlayer.addListener(exoPlayerListener)
    }

    override fun setSurface(surface: Surface) {
        exoPlayer.setVideoSurface(surface)
    }

    override fun setDataSource(dataPath: String) {
        Log.d(TAG, "setDataSource: dataPath=${dataPath}")
        if (isLooping) {
            exoPlayer.repeatMode = Player.REPEAT_MODE_ALL
        } else {
            exoPlayer.repeatMode = Player.REPEAT_MODE_OFF
        }
        val uri = Uri.parse(dataPath)
        videoSource = getTextSource(uri)
        reset()
    }

    private fun getTextSource(uri: Uri): MediaSource? {     //subTitle = Uri.parse(file.getAbsolutePath().toString());  file -- the local .srt file
        //todo C.SELECTION_FLAG_AUTOSELECT language MimeTypes
        val textFormat: Format = Format.Builder()
            .setSampleMimeType(MimeTypes.APPLICATION_SUBRIP)
            .setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
            .build()

        val subtitle: MediaItem.SubtitleConfiguration = MediaItem.SubtitleConfiguration.Builder(uri)
            .setMimeType(checkNotNull(textFormat.sampleMimeType))
            .setLanguage(textFormat.language)
            .setSelectionFlags(textFormat.selectionFlags).build()

        val authority = uri.authority
        Log.d(TAG, "getTextSource, authority=${authority}")
        val factory = if (arrayOf("http").contains(authority)) {
            httpDataSource
        } else {
            fileDataSource
        }
        val textMediaSource: MediaSource = SingleSampleMediaSource.Factory(
            DefaultDataSource.Factory(
                context,
                factory
            )
        ).createMediaSource(subtitle, C.TIME_UNSET)
        return textMediaSource
    }

    override fun prepareAsync() {
        videoSource?.run {
            exoPlayer.setMediaSource(this)
            exoPlayer.prepare()
            exoPlayer.playWhenReady = true
        }

    }

    override fun start() {
        exoPlayer.playWhenReady = true
    }

    override fun pause() {
        exoPlayer.playWhenReady = false
    }

    override fun stop() {
        exoPlayer.stop()
    }

    override fun reset() {
        exoPlayer.stop(true)
    }

    override fun release() {
        exoPlayer.release()
    }

    override fun setLooping(looping: Boolean) {
        this.isLooping = looping
    }

    override fun setScreenOnWhilePlaying(onWhilePlaying: Boolean) {
    }

    override fun getVideoInfo(): VideoInfo {
        return VideoInfo(currVideoWidth, currVideoHeight)
    }

    override fun getPlayerType(): String {
        return "ExoPlayerImpl"
    }
}